﻿using UnityEngine;
using System.IO;
using System.Text;
using System;

namespace Framework
{
    internal sealed class LogFileCollector
    {
        private FileStream _fileStream;
        private BinaryWriter _logWriter;
        private StreamReader _logReader;
        private string _fileName;
        private string _logFilePath;
        private StringBuilder _logNormalBuilder;
        private StringBuilder _logWarnBuilder;
        private StringBuilder _logErrorBuilder;
        private readonly char[] LineBreak = "\r\n".ToCharArray();

        public LogFileCollector(string fileName) 
        {
            _fileName = fileName;
#if UNITY_EDITOR
            _logFilePath = Application.dataPath.Replace("Assets", "") + fileName;
#else
            _logFilePath = Application.persistentDataPath + "/" + fileName;
#endif
            string oldLogFilePath = _logFilePath + ".old";

            if (FileHelper.IsFileExists(_logFilePath)) 
            {
                if (FileHelper.IsFileExists(oldLogFilePath))
                {
                    FileHelper.DeleteFile(oldLogFilePath);
                }
                FileHelper.ChangeDirOrFileName(_logFilePath, _fileName + ".old");
            }
            _fileStream = new FileStream(_logFilePath, FileMode.Create, FileAccess.ReadWrite);
            _logWriter = new BinaryWriter(_fileStream);
            _logReader = new StreamReader(_fileStream);
            _logNormalBuilder = new StringBuilder();
            _logWarnBuilder = new StringBuilder();
            _logErrorBuilder = new StringBuilder();
        }

        public void CollectNormalLog(object msg)
        {
            lock (this) 
            {
                string log = (msg == null) ? "--Empty--" : msg.ToString();
                DateTime now = DateTime.Now;
                _logNormalBuilder.AppendFormat("{0}-{1}-{2} {3}:{4}:{5}.{6} NORMAL==>", 
                    now.Year, now.Month, now.Day, now.Hour, now.Minute, now.Second, now.Millisecond);          
                _logWriter.Write(_logNormalBuilder.ToString().ToCharArray());
                _logWriter.Write(log.ToCharArray());
                _logWriter.Write(LineBreak);
                _logWriter.Flush();
                _logNormalBuilder.Remove(0, _logNormalBuilder.Length);               
            }
        }

        public void CollectWarnLog(object msg) 
        {
            lock (this)
            {
                string log = (msg == null) ? "--Empty--" : msg.ToString();
                DateTime now = DateTime.Now;
                _logWarnBuilder.AppendFormat("{0}-{1}-{2} {3}:{4}:{5}.{6}   WARN==>", 
                    now.Year, now.Month, now.Day, now.Hour, now.Minute, now.Second, now.Millisecond);
                _logWriter.Write(_logWarnBuilder.ToString().ToCharArray());
                _logWriter.Write(log.ToCharArray());
                _logWriter.Write(LineBreak);
                _logWriter.Flush();
                _logWarnBuilder.Remove(0, _logWarnBuilder.Length);                
            }
        }

        public void CollectErrorLog(object msg)
        {
            lock (this)
            {
                string log = (msg == null) ? "--Empty--" : msg.ToString();
                DateTime now = DateTime.Now;
                _logErrorBuilder.AppendFormat("{0}-{1}-{2} {3}:{4}:{5}.{6}  ERROR==>",
                    now.Year, now.Month, now.Day, now.Hour, now.Minute, now.Second, now.Millisecond);
                _logWriter.Write(_logErrorBuilder.ToString().ToCharArray());
                _logWriter.Write(log.ToCharArray());
                _logWriter.Write(LineBreak);
                _logWriter.Flush();
                _logErrorBuilder.Remove(0, _logErrorBuilder.Length);                 
            }
        }

        public string GetOldLogStr()
        {
            return FileHelper.ReadText(_logFilePath + ".old");
        }

        public string GetCurrrentLogStr()
        {
            string logStr;
            lock (this)
            {
                _fileStream.Seek(0, SeekOrigin.Begin);
                logStr = _logReader.ReadToEnd();
                _fileStream.Seek(0, SeekOrigin.End);
            }
            return logStr;
        }

        ~LogFileCollector()
        {
#if UNITY_EDITOR
            if (_logWriter != null) 
            {
                _logWriter.Close();
                _logWriter.Dispose();
                _logWriter = null;
            }

            if (_logReader != null) 
            {
                _logReader.Close();
                _logReader.Dispose();
                _logReader = null;
            }

            if (_fileStream != null) 
            {
                _fileStream.Close();
                _fileStream.Dispose();
                _fileStream = null;
            }
            _fileName = null;
            _logFilePath = null;
            _logNormalBuilder = null;
            _logWarnBuilder = null;
            _logErrorBuilder = null;
#endif
        }
    }
}
